/**
 *  TextMash - simple IDE for Clojure
 *  
 *  Copyright (C) 2010 Aleksander Naszko
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package pl.olek.jruce;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

/**
 *
 * @author anaszko
 */
public abstract class GroupSender {

//    final public static Logger logger = Logger.getLogger(GroupSender.class.getName());

    Scheduled scheduled;

    MulticastSocket socket;

    InetAddress address;

    int port;

    public abstract void send(OutputStream output) throws Exception;

    public void send(byte[] buffer) throws Exception {
        socket.send(new DatagramPacket(buffer, 0, buffer.length,
                address, port));
    }

    public static ByteArrayOutputStream getBuffer() {
        return new ByteArrayOutputStream(4096);
    }

//    public static void send(final String groupName, Object obj) {
//         try {
//          MulticastSocket  socket = new MulticastSocket();
//          InetAddress  address = InetAddress.getByName(GroupReceiver.extractIp(groupName));
//        int port = GroupReceiver.extractPort(groupName);
//
//        ByteArrayOutputStream output = getBuffer();
//        new ObjectOutputStream(output).writeObject(obj);
//        output.flush();
//         byte[] buffer = output.toByteArray();
//
//            socket.send(new DatagramPacket(buffer, 0, buffer.length,
//                    address, port));
//
//            socket.close();
//
//               } catch (Exception e) {
//            logger.log(Level.SEVERE, null, e);
//            throw new RuntimeException(e);
//        }
//    }
    public GroupSender(final String groupName) {
        try {
            socket = new MulticastSocket();
            address = InetAddress.getByName(GroupReceiver.extractIp(groupName));

            port = GroupReceiver.extractPort(groupName);
            ByteArrayOutputStream output = getBuffer();
            send((OutputStream) output);
            output.flush();

            byte[] buffer = output.toByteArray();

            socket.send(new DatagramPacket(buffer, 0, buffer.length,
                    address, port));

            socket.close();

        } catch (Exception e) {
//            logger.log(Level.SEVERE, null, e);
            throw new RuntimeException(e);
        }
    }

    public GroupSender(final String groupName, final long frequency) {

        try {

            socket = new MulticastSocket();

            address = InetAddress.getByName(GroupReceiver.extractIp(groupName));

            port = GroupReceiver.extractPort(groupName);

            scheduled = new Scheduled(frequency) {

                ByteArrayOutputStream output = getBuffer();

                @Override
                public void run() {

                    try {

                        output.reset();

                        send((OutputStream) output);

                        output.flush();

                        byte[] buffer = output.toByteArray();

                        socket.send(new DatagramPacket(buffer, 0, buffer.length,
                                address, port));

                    } catch (Exception e) {
//                        logger.log(Level.SEVERE, null, e);
                        throw new RuntimeException(e);
                    }
                }

                @Override
                public void end() {
                    socket.close();
                }
            };

        } catch (Exception e) {
//            logger.log(Level.SEVERE, null, e);
            throw new RuntimeException(e);
        }
    }

    public void join(){
        scheduled.join();
    }

    public void fire() {
        if (scheduled == null) {
            throw new UnsupportedOperationException();
        }
        scheduled.fire();
    }

    public void stop() {
        if (scheduled == null) {
            throw new UnsupportedOperationException();
        }
        scheduled.stop();
    }
}
